﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using ApocDev.TownsApi.Aspects;

namespace ApocDev.TownsApi
{
    public class GraphicsIni
    {
        public GraphicsIni()
        {
            Parse();
        }

        public string IconFile { get; set; }
        public string CursorFile { get; set; }
        public string MainMenuBackgroundFile { get; set; }
        public string LoadingFile { get; set; }
        public string SmpLogoFile { get; set; }
        public string TownsLogoFile { get; set; }
        public string TilesetFontFile { get; set; }

        public Dictionary<string, GraphicsObject> Objects { get; set; }

        private void Parse()
        {
            string filePath = Path.Combine(Path.GetDirectoryName(ModFiles.BaseDirectory), "graphics.ini");
            Objects = new Dictionary<string, GraphicsObject>();

            foreach (string line in File.ReadAllLines(filePath))
            {
                // Empty and comment lines.
                if (string.IsNullOrWhiteSpace(line) || line.Trim().StartsWith("#"))
                    continue;

                if (line.StartsWith("ICON_FILE"))
                    IconFile = line.Remove(0, line.IndexOf("=")).Trim();
                else if (line.StartsWith("CURSOR_FILE"))
                    CursorFile = line.Remove(0, line.IndexOf("=")).Trim();
                else if (line.StartsWith("MAINMENU_BG_FILE"))
                    MainMenuBackgroundFile = line.Remove(0, line.IndexOf("=")).Trim();
                else if (line.StartsWith("LOADING_FILE"))
                    LoadingFile = line.Remove(0, line.IndexOf("=")).Trim();
                else if (line.StartsWith("SMP_LOGO_FILE"))
                    SmpLogoFile = line.Remove(0, line.IndexOf("=")).Trim();
                else if (line.StartsWith("TOWNS_LOGO_FILE"))
                    TownsLogoFile = line.Remove(0, line.IndexOf("=")).Trim();
                else if (line.StartsWith("TILESET_FONT_FILE"))
                    TilesetFontFile = line.Remove(0, line.IndexOf("=")).Trim();
                else
                {
                    try
                    {
                        // All the other handling...
                        string[] nameValSplit = line.Split(new[] {"[", "]"}, StringSplitOptions.RemoveEmptyEntries);
                        string name = nameValSplit[0];

                        GraphicsObject obj;
                        if (!Objects.TryGetValue(name, out obj))
                        {
                            obj = new GraphicsObject();
                            obj.Name = name;
                            Objects.Add(name, obj);
                        }


                        string[] value =
                            nameValSplit.Last()
                                        .Split(new[] {"="}, StringSplitOptions.RemoveEmptyEntries)
                                        .Select(v => v.Trim())
                                        .ToArray();
                        switch (value[0].Trim())
                        {
                            case "TILE_X":
                                obj.TileX = int.Parse(value[1]);
                                break;
                            case "TILE_Y":
                                obj.TileY = int.Parse(value[1]);
                                break;
                            case "TILE_HEIGHT":
                                obj.TileHeight = int.Parse(value[1]);
                                break;
                            case "TILE_WIDTH":
                                obj.TileWidth = int.Parse(value[1]);
                                break;
                            case "TEXTURE_FILE":
                                obj.TextureFile = value[1];
                                break;
                            case "COLOR_MINIMAP":
                                obj.ColorMinimap = value[1];
                                break;
                            case "CARRY_OFFSET":
                                obj.CarryOffset = value[1];
                                break;
                            case "HEAD_OFFSET":
                                obj.HeadOffset = value[1];
                                break;
                            case "BODY_OFFSET":
                                obj.BodyOffset = value[1];
                                break;
                            case "LEGS_OFFSET":
                                obj.LegsOffset = value[1];
                                break;
                            case "FEET_OFFSET":
                                obj.FeetOffset = value[1];
                                break;
                            case "WEAPON_OFFSET":
                                obj.WeaponOffset = value[1];
                                break;
                            case "ANIMATION_TILES":
                                obj.AnimationTiles = value[1];
                                break;
                            case "ANIMATION_FRAME_DELAY":
                                obj.AnimationFrameDelay = value[1];
                                break;
                            case "TILE_HEIGHT_OFFSET":
                                obj.TileHeightOffset = int.Parse(value[1]);
                                break;
                            case "COLOR":
                            case "COLOT": // typo. GG ;)
                                obj.Color = value[1];
                                break;
                            case "TILE_WIDTH_OFFSET":
                                obj.TileWidthOffset = int.Parse(value[1]);
                                break;
                            default:
                                Debug.WriteLine("Unhandled graphics.ini line: " + line);
                                break;
                        }
                    }
                    catch
                    {
                        Debug.WriteLine("Unhandled graphics.ini line: " + line);
                    }
                }
            }
        }

        //[NotifyPropertyChanged]
        public class GraphicsObject
        {
            public GraphicsObject()
            {
                TileHeight = 32;
                TileWidth = 64;
            }

            private string _textureFile;
            public int TileX { get; set; }
            public int TileY { get; set; }
            public int TileHeight { get; set; }
            public int TileHeightOffset { get; set; }
            public int TileWidth { get; set; }
            public int TileWidthOffset { get; set; }
            public string CarryOffset { get; set; }
            public string HeadOffset { get; set; }
            public string BodyOffset { get; set; }
            public string LegsOffset { get; set; }
            public string FeetOffset { get; set; }
            public string WeaponOffset { get; set; }
            public string AnimationTiles { get; set; }
            public string AnimationFrameDelay { get; set; }
            public string ColorMinimap { get; set; }
            public string Color { get; set; }

            public string TextureFile
            {
                get
                {
                    if (string.IsNullOrWhiteSpace(_textureFile))
                    {
                        string parentName =
                            Name.Split(new[] {'_'}, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
                        _textureFile = ModFiles.Graphics.Objects[parentName].TextureFile;
                    }
                    return _textureFile;
                }
                set { _textureFile = value; }
            }

            public string Name { get; set; }

            public override string ToString()
            {
                return Name;
            }

            public Image GetImage(int animationTile = 0)
            {
                // Air has no image!!
                if (Name == "_AIR")
                    return new Bitmap(64, 64);

                int x = (TileX + animationTile) * 64;
                int y = TileY * 32;

                var img = Image.FromFile(Path.Combine(ModFiles.BaseDirectory, "graphics", TextureFile));
                var srcRect = new Rectangle(x + TileWidthOffset, y + TileHeightOffset, TileWidth, TileHeight);
                Image imgOut = new Bitmap(64, TileHeight, img.PixelFormat);
                using (var g = Graphics.FromImage(imgOut))
                {
                    g.DrawImage(img, new Rectangle(0, 0, 64, TileHeight), srcRect, GraphicsUnit.Pixel);
                }

                return imgOut;
            }
        }
    }
}